home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / SBDAC.ARJ / DACDMA.C < prev    next >
C/C++ Source or Header  |  1992-02-09  |  5KB  |  223 lines

  1. /* Output to SB DAC using DMA mode */
  2.  
  3. #include <stdio.h>
  4. #include <dos.h>
  5. #include <conio.h>
  6. #include <io.h>
  7. #include <alloc.h>
  8. #include <dos.h>
  9. #include <stdlib.h>
  10. #include <alloc.h>
  11.  
  12.  
  13. /* Defines for Soundblaster and Soundblaster Pro IO address */
  14. #define LEFT_FM_STATUS        0x00    /* Pro only */
  15. #define LEFT_FM_ADDRESS     0x00    /* Pro only */
  16. #define LEFT_FM_DATA        0x01    /* Pro only */
  17. #define RIGHT_FM_STATUS     0x02    /* Pro only */
  18. #define RIGHT_FM_ADDRESS    0x02    /* Pro only */
  19. #define RIGHT_FM_DATA        0x03    /* Pro only */
  20. #define MIXER_ADDRESS        0x04    /* Pro only */
  21. #define MIXER_DATA        0x05    /* Pro only */
  22. #define DSP_RESET        0x06
  23. #define FM_STATUS        0x08
  24. #define FM_ADDRESS        0x08
  25. #define FM_DATA         0x09
  26. #define DSP_READ_DATA        0x0A
  27. #define DSP_WRITE_DATA        0x0C
  28. #define DSP_WRITE_STATUS    0x0C
  29. #define DSP_DATA_AVAIL        0x0E
  30. #define CD_ROM_DATA        0x10    /* Pro only */
  31. #define CD_ROM_STATUS        0x11    /* Pro only */
  32. #define CD_ROM_RESET        0x12    /* Pro only */
  33. #define CD_ROM_ENABLE        0x13    /* Pro only */
  34.  
  35. #define ADLIB_FM_STATUS     0x388
  36. #define ADLIB_FM_ADDRESS    0x388
  37. #define ADLIB_FM_DATA        0x389
  38.  
  39. /* Defines for 8237 DMA Controller IO addresses */
  40. #define DMA        0x00
  41. #define CH0_BASE    DMA+0
  42. #define CH0_COUNT   DMA+1
  43. #define CH1_BASE    DMA+2
  44. #define CH1_COUNT   DMA+3
  45. #define CH2_BASE    DMA+4
  46. #define CH2_COUNT   DMA+5
  47. #define CH3_BASE    DMA+6
  48. #define CH3_COUNT   DMA+7
  49. #define DMA_STATUS  DMA+8
  50. #define DMA_CMD     DMA+8
  51. #define DMA_REQUEST DMA+9
  52. #define DMA_MASK    DMA+10
  53. #define DMA_MODE    DMA+11
  54. #define DMA_FF      DMA+12
  55. #define DMA_TMP     DMA+13
  56. #define DMA_CLEAR   DMA+13
  57. #define DMA_CLRMSK  DMA+14
  58. #define DMA_WRMSK   DMA+15
  59. #define DMAPAGE     0x80
  60.  
  61. int InitSB(void);
  62. extern unsigned IOaddr;
  63. extern unsigned IRQ;
  64.  
  65. void far interrupt (*OldIRQ)();
  66. volatile int DMA_complete;
  67.  
  68. /* Define a useful macro for writing data to the DAC */
  69. #define writedac(x) { while(inportb(IOaddr+DSP_WRITE_STATUS) & 0x80); \
  70.               outportb(IOaddr+DSP_WRITE_DATA,(x)); }
  71.  
  72. /* Interrupt handler for DMA complete IRQ from Soundblaster */
  73. void far interrupt SBHandler()
  74. {
  75.     enable();
  76.     DMA_complete = 1;
  77.     outportb(0x20,0x20);
  78. }
  79.  
  80. /* Sets the sample rate to be used for digitising or playback */
  81. void SetSampleRate(unsigned rate)
  82. {
  83.     unsigned char tc;
  84.  
  85.     tc = (unsigned char)(256 - (1000000/rate));
  86.  
  87.     writedac(0x40);  /* Command byte for sample rate */
  88.     writedac(tc);    /* Sample rate time constant */
  89. }
  90.  
  91. void SetVoice(int state)
  92. {
  93.     writedac((state) ? 0xd1 : 0xd3);   /* Command bytes for voice:  */
  94.                        /* 0xD1    -    voice on        */
  95.                        /* 0xD3    -    voice off        */
  96. }
  97.  
  98.  
  99.  
  100.  
  101. void OutVoice(char *data, unsigned dlen)
  102. {
  103.     int t;
  104.     long addr;
  105.     register int i;
  106.     unsigned char im, tm;
  107.  
  108.     DMA_complete = 0;
  109.  
  110.     /* Enable interrupts on PIC */
  111.     im = inportb(0x21);
  112.     tm = ~(1 << IRQ);
  113.     outportb(0x21,im & tm);
  114.     enable();
  115.  
  116.     /* Set DMA mode */
  117.     outportb(DMA_MASK,5);
  118.     outportb(DMA_FF,0);
  119.     outportb(DMA_MODE,0x49);
  120.  
  121.     /* Set transfer address */
  122.     addr = ((long)FP_SEG(data) << 4) + (long)FP_OFF(data);
  123.     t = (int)(addr >> 16);
  124.     outportb(DMAPAGE+3,t);
  125.     t = (int)(addr & 0xffff);
  126.     outportb(CH1_BASE,t & 0xff);
  127.     outportb(CH1_BASE,t >> 8);
  128.  
  129.     /* Set transfer length byte count */
  130.     outportb(CH1_COUNT,dlen & 0xff);
  131.     outportb(CH1_COUNT,dlen >> 8);
  132.  
  133.     /* Unmask DMA channel */
  134.     outportb(DMA_MASK,1);
  135.  
  136.     /* Setup Soundblaster for transfer */
  137.     writedac(0x48);   /* One command byte used for DMA DAC transfer */
  138.  
  139.     /* Write length */
  140.     writedac(dlen & 0xff);
  141.     writedac(dlen >> 8);
  142.  
  143.     writedac(0x14);   /* Second command byte for DMA DAC transfer */
  144.  
  145.     /* Write length */
  146.     writedac(dlen & 0xff);
  147.     writedac(dlen >> 8);
  148. }
  149.  
  150. void main(int argc, char *argv[])
  151. {
  152.     FILE *f;
  153.     char *raw;
  154.     long sample_len;
  155.     register int j, i;
  156.     unsigned sl, tmp, nr, sr;
  157.     unsigned char tm;
  158.  
  159.     if(argc < 2)
  160.     {
  161.     puts("Usage: dacdma sample [sample rate]");
  162.     exit(1);
  163.     }
  164.  
  165.     if(InitSB())
  166.     {
  167.     printf("Could not find Soundblaster!\n");
  168.     exit(1);
  169.     }
  170.     printf("Found Soundblaster at %xh.\n",IOaddr);
  171.  
  172.     f = fopen(argv[1],"rb");
  173.     if(f == NULL)
  174.     {
  175.     printf("Could not open sample file %s\n",argv[1]);
  176.     exit(1);
  177.     }
  178.     sample_len = filelength(fileno(f));
  179.     if(sample_len > 64000)
  180.         sl = 64000;
  181.     else
  182.         sl = (int)sample_len;
  183.  
  184.     raw = (signed char *)farmalloc((unsigned long)sl);
  185.     nr = fread(raw,1,sl,f);
  186.  
  187.     fclose(f);
  188.  
  189.  
  190.     /* Insert our IRQ handler into interrupt chain */
  191.     disable();
  192.     OldIRQ = getvect(0x08 + IRQ);
  193.     setvect(0x08 + IRQ,SBHandler);
  194.     enable();
  195.  
  196.     sr = 11000;
  197.     if(argc == 3)
  198.     sr = atoi(argv[2]);
  199.  
  200.     SetSampleRate(sr);
  201.     SetVoice(1);
  202.  
  203.     OutVoice(raw,sl);
  204.  
  205.     while(!kbhit() && !DMA_complete)
  206.     ;
  207.     if(!DMA_complete)
  208.     getch();
  209.  
  210.     SetVoice(0);
  211.  
  212.     /* Restore old IRQ vector */
  213.     disable();
  214.     setvect(0x08 + IRQ,OldIRQ);
  215.     tm = inportb(0x21);
  216.     outportb(0x21,tm | (1 << IRQ));
  217.     enable();
  218.  
  219.     farfree(raw);
  220.  
  221.     exit(0);
  222. }
  223.